package com.wanglin.mqttandroidclient

import android.app.Application
import android.content.Context
import android.util.Log
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*
import kotlin.properties.Delegates

class MyApplication : Application() {
    lateinit var baseURL: String

    //定义回调方法，接收mqtt订阅消息
    lateinit var onMessageArrived: ((msg: String) -> Unit)
    fun setOnDismissListener(onMessageArrived: ((msg: String) -> Unit)) {
        this.onMessageArrived = onMessageArrived
    }

    /*全局单例 */
    companion object {

        private const val TAG = "MyApplication"

        //全局上下文
        lateinit var context: Context

        // 单例不会是null   所以使用notNull委托
        var instance: MyApplication by Delegates.notNull()

        //MQTT
        const val SUBSCRIPTION_TOPIC = "subTopic"
        const val PUBLISH_TOPIC = "pubTopic"
        const val MQTT_SERVER_USERNAME = "yf"
        const val MQTT_SERVER_PASSWORD = "yf123."
        lateinit var mqttAndroidClient: MqttAndroidClient
        lateinit var mqttUrl: String
        var clientId = "androidClient"


    }

    override fun onCreate() {
        super.onCreate()


        instance = this

        /*全局上下文*/
        context = applicationContext


        initMQTT()

    }

    private fun initMQTT() {
        mqttUrl = "tcp://192.168.0.141:1883"
        //创建mqtt连接
        clientId += System.currentTimeMillis()
        mqttAndroidClient = MqttAndroidClient(applicationContext, mqttUrl, clientId)
        //设置mqtt连接状态回调
        mqttAndroidClient.setCallback(object : MqttCallbackExtended  {
            override fun connectComplete(reconnect: Boolean, serverURI: String) {
                if (reconnect) {
                    Log.d("mqtt", "Reconnected to : $serverURI")
                    // Because Clean Session is true, we need to re-subscribe
                    subscribeToTopic()
                } else {
                    Log.d("mqtt", ("Connected to: $serverURI"))
                }
            }

            override fun connectionLost(cause: Throwable) {
                Log.d("mqtt", "The Connection was lost.")
            }

            @Throws(java.lang.Exception::class)
            override fun messageArrived(topic: String, message: MqttMessage) {
                onMessageArrived.invoke(String(message.payload))
                Log.d("mqtt", "Incoming message: " + String(message.payload))
            }

            override fun deliveryComplete(token: IMqttDeliveryToken) {}
        } )


        //设置mqtt连接选项(自动重连)
        val mqttConnectOptions = MqttConnectOptions()
        mqttConnectOptions.isAutomaticReconnect = true
        mqttConnectOptions.isCleanSession = false
        mqttConnectOptions.userName = MQTT_SERVER_USERNAME
        mqttConnectOptions.password = MQTT_SERVER_PASSWORD.toCharArray()

        //连接mqtt
        Log.d("mqtt", "Connecting to $mqttUrl");

        mqttAndroidClient.connect(mqttConnectOptions, null, object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken) {
                //断开连接的缓冲选项
                val disconnectedBufferOptions = DisconnectedBufferOptions()
                disconnectedBufferOptions.isBufferEnabled = true
                disconnectedBufferOptions.bufferSize = 100
                disconnectedBufferOptions.isPersistBuffer = false
                disconnectedBufferOptions.isDeleteOldestMessages = false
                mqttAndroidClient.setBufferOpts(disconnectedBufferOptions)

                //订阅主题
                subscribeToTopic()
            }

            override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                Log.d("mqtt", "Failed to connect to: $mqttUrl")
            }
        })
    }

    //订阅
    fun subscribeToTopic() {
        //订阅动作回调
        mqttAndroidClient.subscribe(SUBSCRIPTION_TOPIC, 0, null, object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken) {
                Log.d("mqtt", "Subscribed!")
            }

            override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                Log.d("mqtt", "Failed to subscribe")

            }
        })
    }

    //发布
    fun publishMessage(publishMessage: String) {
        val message = MqttMessage()
        message.payload = publishMessage.toByteArray()
        mqttAndroidClient.publish(PUBLISH_TOPIC, message)
        Log.d("mqtt", "Message Published")
        if (!mqttAndroidClient.isConnected) {
            Log.d(
                "mqtt",
                mqttAndroidClient.bufferedMessageCount.toString() + " messages in buffer."
            )
        }
    }







}






